package cn.song.h5.app.controller;

import cn.hutool.json.JSONUtil;
import cn.song.h5.app.config.AlipayConfig;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.*;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * 支付宝控制器
 *
 * @author SongRenShuo
 * @date 2023/12/26
 */
@RestController
@RequestMapping("H5app")
public class AlipayController {

    /**
     * 编码
     */
    private final String ENCODE = "UTF-8";
    @Autowired
    private HttpServletRequest request;

    /**
     * 付款
     *
     * @return {@link String }
     * @date: 2024/01/26
     * @author SongRenShuo
     */
    @RequestMapping("pay")
    public String pay( ) throws Exception {
        if (getParameter("WIDout_trade_no") != null) {
            // 商户订单号，商户网站订单系统中唯一订单号，必填
            String out_trade_no =getParameter("WIDout_trade_no");
            // 订单名称，必填
            String subject =getParameter("WIDsubject");
            // 付款金额，必填
            String total_amount = getParameter("WIDtotal_amount");
            // 商品描述，可空
            String body =getParameter("WIDbody");
            // 超时时间 可空
            String timeout_express = "2m";
            // 销售产品码 必填
            String product_code = "QUICK_WAP_WAY";
            /**********************/
            // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
            // 调用RSA签名方式
            AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
            AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();
            // 设置异步通知地址
            alipay_request.setNotifyUrl(AlipayConfig.notify_url);
            // 设置同步地址
            alipay_request.setReturnUrl(AlipayConfig.return_url);

            // 封装请求支付信息
            AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
            model.setOutTradeNo(out_trade_no);
            model.setSubject(subject);
            model.setTotalAmount(total_amount);
            model.setBody(body);
            model.setTimeoutExpress(timeout_express);
            model.setProductCode(product_code);
            alipay_request.setBizModel(model);


            // form表单生产
            String form = "";
            try {
                // 调用SDK生成表单
                form = client.pageExecute(alipay_request).getBody();
               return form;
            } catch (AlipayApiException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return "SDK生成表单异常："+e.getMessage();
            }
        }
        return "商户订单号不可以为空";
    }


    /**
     * 交易查询
     *
     * @return {@link String }
     * @date: 2024/01/26
     * @author SongRenShuo
     */
    @RequestMapping("query")
    public String query( ) throws Exception {
        if (getParameter("WIDout_trade_no") != null || getParameter("WIDtrade_no") != null) {
            // 商户订单号，商户网站订单系统中唯一订单号，必填
            String out_trade_no = getParameter("WIDout_trade_no");
            // 支付宝交易号
            String trade_no = getParameter("WIDtrade_no");
            /**********************/
            // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
            AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
            AlipayTradeQueryRequest alipay_request = new AlipayTradeQueryRequest();

            AlipayTradeQueryModel model = new AlipayTradeQueryModel();
            model.setOutTradeNo(out_trade_no);
            model.setTradeNo(trade_no);
            alipay_request.setBizModel(model);

            AlipayTradeQueryResponse alipay_response = client.execute(alipay_request);
            String body = alipay_response.getBody();

            System.out.println("交易查询：" + JSONUtil.formatJsonStr(body));
            return body;
        }
        return "商户订单号和支付宝交易号不能同时为空";
    }

    /**
     * 退款
     *
     * @return {@link String }
     * @date: 2024/01/26
     * @author SongRenShuo
     */
    @RequestMapping("refund")
    public String refund( ) throws Exception {
        if (getParameter("WIDout_trade_no") != null || getParameter("WIDtrade_no") != null) {
            // 商户订单号和支付宝交易号不能同时为空。 trade_no、  out_trade_no如果同时存在优先取trade_no
            // 商户订单号，和支付宝交易号二选一
            String out_trade_no = getParameter("WIDout_trade_no");
            // 支付宝交易号，和商户订单号二选一
            String trade_no = getParameter("WIDtrade_no");
            // 退款金额，不能大于订单总金额
            String refund_amount = getParameter("WIDrefund_amount");
            // 退款的原因说明
            String refund_reason = getParameter("WIDrefund_reason");
            // 标识一次退款请求，同一笔交易多次退款需要保证唯一，如需部分退款，则此参数必传。
            String out_request_no = getParameter("WIDout_request_no");
            /**********************/
            // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
            AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
            AlipayTradeRefundRequest alipay_request = new AlipayTradeRefundRequest();

            AlipayTradeRefundModel model = new AlipayTradeRefundModel();
            model.setOutTradeNo(out_trade_no);
            model.setTradeNo(trade_no);
            model.setRefundAmount(refund_amount);
            model.setRefundReason(refund_reason);
            model.setOutRequestNo(out_request_no);
            alipay_request.setBizModel(model);

            AlipayTradeRefundResponse alipay_response = client.execute(alipay_request);
            String body = alipay_response.getBody();
            System.out.println("退款：" + JSONUtil.formatJsonStr(body));
            return body;
        }
        return "商户订单号和支付宝交易号不能同时为空";
    }

    /**
     * 退款查询
     *
     * @return {@link String }
     * @date: 2024/01/26
     * @author SongRenShuo
     */
    @RequestMapping("refundQuery")
    public String refundQuery( ) throws Exception {
        if (getParameter("WIDout_trade_no") != null || getParameter("WIDtrade_no") != null && getParameter("WIDout_request_no") != null) {
            // 商户订单号和支付宝交易号不能同时为空。 trade_no、  out_trade_no如果同时存在优先取trade_no
            // 商户订单号，和支付宝交易号二选一
            String out_trade_no = getParameter("WIDout_trade_no");
            // 支付宝交易号，和商户订单号二选一
            String trade_no = getParameter("WIDtrade_no");
            // 请求退款接口时，传入的退款请求号，如果在退款请求时未传入，则该值为创建交易时的外部交易号
            String out_request_no = getParameter("WIDout_request_no");
            /**********************/
            // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
            AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
            AlipayTradeFastpayRefundQueryRequest alipay_request = new AlipayTradeFastpayRefundQueryRequest();

            AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();
            model.setOutTradeNo(out_trade_no);
            model.setTradeNo(trade_no);
            model.setOutRequestNo(out_request_no);
            alipay_request.setBizModel(model);

            AlipayTradeFastpayRefundQueryResponse alipay_response = client.execute(alipay_request);
            String body = alipay_response.getBody();
            System.out.println("退款查询：" + JSONUtil.formatJsonStr(body));
            return body;
        }
        return "商户订单号和支付宝交易号不能同时为空";
    }

    /**
     * 交易关闭
     *
     * @return {@link String }
     * @date: 2024/01/26
     * @author SongRenShuo
     */
    @RequestMapping("close")
    public String close( ) throws Exception {

        if (getParameter("WIDout_trade_no") != null || getParameter("WIDtrade_no") != null) {
            // 商户订单号和支付宝交易号不能同时为空。 trade_no、  out_trade_no如果同时存在优先取trade_no
            // 商户订单号，和支付宝交易号二选一
            String out_trade_no = getParameter("WIDout_trade_no");
            // 支付宝交易号，和商户订单号二选一
            String trade_no = getParameter("WIDtrade_no");
            /**********************/
            // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
            AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
            AlipayTradeCloseRequest alipay_request = new AlipayTradeCloseRequest();

            AlipayTradeCloseModel model = new AlipayTradeCloseModel();
            model.setOutTradeNo(out_trade_no);
            model.setTradeNo(trade_no);
            alipay_request.setBizModel(model);

            AlipayTradeCloseResponse alipay_response = client.execute(alipay_request);
            String body = alipay_response.getBody();
            System.out.println("交易关闭：" + JSONUtil.formatJsonStr(body));
            return body;
        }
        return "商户订单号和支付宝交易号不能同时为空";
    }


    /**
     * 查询对账单下载地址
     *
     * @return {@link String }
     * @date: 2024/01/26
     * @author SongRenShuo
     */
    @RequestMapping("downloadurl")
    public String downloadurl( ) throws Exception {

        if (getParameter("WIDbill_type") != null && getParameter("WIDbill_date") != null) {
            // 账单类型，商户通过接口或商户经开放平台授权后其所属服务商通过接口可以获取以下账单类型：trade、signcustomer；
            // trade指商户基于支付宝交易收单的业务账单；signcustomer是指基于商户支付宝余额收入及支出等资金变动的帐务账单；
            String bill_type = getParameter("WIDbill_type");
            // 账单时间：日账单格式为yyyy-MM-dd，月账单格式为yyyy-MM。
            String bill_date = getParameter("WIDbill_date");
            /**********************/
            // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
            AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
            AlipayDataDataserviceBillDownloadurlQueryRequest alipay_request = new AlipayDataDataserviceBillDownloadurlQueryRequest();

            AlipayDataDataserviceBillDownloadurlQueryModel model = new AlipayDataDataserviceBillDownloadurlQueryModel();
            model.setBillType(bill_type);
            model.setBillDate(bill_date);
            alipay_request.setBizModel(model);

            AlipayDataDataserviceBillDownloadurlQueryResponse alipay_response = client.execute(alipay_request);
            String downloadUrl = alipay_response.getBillDownloadUrl();
            System.out.println("查询对账单下载地址：" + downloadUrl);
            return downloadUrl;
        }
        return "账单类型或账单时间为空";
    }

    /**
     * 获取参数值
     *
     * @param name 名字
     * @return {@link String }
     * @date: 2024/01/26
     * @author SongRenShuo
     */
    public String getParameter(String name) throws Exception {

        return new String(this.request.getParameter(name).getBytes(ENCODE), ENCODE);
    }
}
